package drds.binlog.parse.driver.packets;

import drds.binlog.parse.driver.utils.Bytes;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;


public class MysqlGtidSet implements GtidSet
{

    public Map<String, UuidSet> sets;

    /**
     * 解析如下格式的字符串为MysqlGTIDSet: 726757ad-4455-11e8-ae04-0242ac110002:1 =>
     * MysqlGtidSet{ sets: { 726757ad-4455-11e8-ae04-0242ac110002: UuidSet{ SID:
     * 726757ad-4455-11e8-ae04-0242ac110002, intervals: [{start:1, stop:2}] } }
     * } 726757ad-4455-11e8-ae04-0242ac110002:1-3 => MysqlGtidSet{ sets: {
     * 726757ad-4455-11e8-ae04-0242ac110002: UuidSet{ SID:
     * 726757ad-4455-11e8-ae04-0242ac110002, intervals: [{start:1, stop:4}] } }
     * } 726757ad-4455-11e8-ae04-0242ac110002:1-3:4 => MysqlGtidSet{ sets: {
     * 726757ad-4455-11e8-ae04-0242ac110002: UuidSet{ SID:
     * 726757ad-4455-11e8-ae04-0242ac110002, intervals: [{start:1, stop:5}] } }
     * } 726757ad-4455-11e8-ae04-0242ac110002:1-3:7-9 => MysqlGtidSet{ sets: {
     * 726757ad-4455-11e8-ae04-0242ac110002: UuidSet{ SID:
     * 726757ad-4455-11e8-ae04-0242ac110002, intervals: [{start:1, stop:4},
     * {start:7, stop: 10}] } } }
     * 726757ad-4455-11e8-ae04-0242ac110002:1-3,726757
     * ad-4455-11e8-ae04-0242ac110003:4 => MysqlGtidSet{ sets: {
     * 726757ad-4455-11e8-ae04-0242ac110002: UuidSet{ SID:
     * 726757ad-4455-11e8-ae04-0242ac110002, intervals: [{start:1, stop:4}] },
     * 726757ad-4455-11e8-ae04-0242ac110003: UuidSet{ SID:
     * 726757ad-4455-11e8-ae04-0242ac110002, intervals: [{start:4, stop:5}] } }
     * }
     *
     * @param gtidData
     * @return
     */
    public static MysqlGtidSet parse(String gtidData)
    {
        Map<String, UuidSet> m;

        if (gtidData == null || gtidData.length() < 1)
        {
            m = new HashMap<String, UuidSet>();
        } else
        {
            String[] uuidStrs = gtidData.split(",");
            m = new HashMap<String, UuidSet>(uuidStrs.length);
            for (int i = 0; i < uuidStrs.length; i++)
            {
                UuidSet uuidSet = UuidSet.parse(uuidStrs[i]);
                m.put(uuidSet.SID.toString(), uuidSet);
            }
        }

        MysqlGtidSet gs = new MysqlGtidSet();
        gs.sets = m;

        return gs;
    }

    @Override
    public byte[] encode() throws IOException
    {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        Bytes.writeUnsigned8IntLittleEndian(byteArrayOutputStream, sets.size());

        for (Map.Entry<String, UuidSet> entry : sets.entrySet())
        {
            byteArrayOutputStream.write(entry.getValue().encode());
        }

        return byteArrayOutputStream.toByteArray();
    }

    @Override
    public void update(String string)
    {
        UuidSet uuidSet = UuidSet.parse(string);
        String sid = uuidSet.SID.toString();
        if (sets.containsKey(sid))
        {
            sets.get(sid).intervals.addAll(uuidSet.intervals);
            sets.get(sid).intervals = UuidSet.combine(sets.get(sid).intervals);
        } else
        {
            sets.put(sid, uuidSet);
        }
    }

    @Override
    public boolean equals(Object o)
    {
        if (o == null) return false;
        if (this == o) return true;

        MysqlGtidSet gs = (MysqlGtidSet) o;
        if (gs.sets == null) return false;

        for (Map.Entry<String, UuidSet> entry : sets.entrySet())
        {
            if (!entry.getValue().equals(gs.sets.get(entry.getKey())))
            {
                return false;
            }
        }

        return true;
    }

    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder();

        for (Map.Entry<String, UuidSet> entry : sets.entrySet())
        {
            if (sb.length() > 0)
            {
                sb.append(",");
            }
            sb.append(entry.getValue().toString());
        }

        return sb.toString();
    }
}
